﻿/*******************************************************************************
 * Copyright © 2016-2020 北京网非科技有限公司 版权所有
 * Author: 北京网非科技有限公司
 * Description: 网非快速开发平台NET
 * Website：http://www.wfdot.com
*********************************************************************************/
using CubicFWNet.Application.SystemManage;
using CubicFWNet.Common;
using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Linq;
using CubicFWNet.Application;
using CubicFWNet.Mvc.Models;
using System;
using System.Reflection;
using System.Collections.Generic;
using System.IO;

namespace CubicFWNet.Mvc
{
    /// <summary>
    /// Controller基类
    /// 必须认证后才能使用
    /// </summary>
    public abstract class ControllerBase : Controller
    {
        protected ResponseResult Result = new ResponseResult();

        private static readonly ModuleApp app = new ModuleApp();
        private CubicFWNet.Data.SystemManage.Model.Module _CurrentModule;        
        private List<CubicFWNet.Data.SystemManage.Model.Module> _UserModules;

        private OperatorModel _OperatorModel;

        protected Guid CurrentUserId
        {
            get
            {
                if (null != _OperatorModel)
                {
                    return _OperatorModel.UserId;
                }
                else
                {
                    return Guid.Empty;
                }
            }
        }

        protected bool IsSystem
        {
            get
            {
                if (null != _OperatorModel)
                {
                    return _OperatorModel.IsSystem;
                }
                else
                {
                    return false;
                }
            }
        }

        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            base.OnActionExecuting(filterContext);

            //检查是否用户已认证
            this._OperatorModel = OperatorProvider.Provider.GetCurrent();
            if (null == this._OperatorModel)
            {
                WebHelper.WriteCookie("cubic_login_error", "overdue");
                filterContext.Result = new RedirectResult("/Login/Index");
                return;
            }

            /*
             * 授权
             * 因为我们权限仅细化到controller级别，只要用户对该controller有权限，那么对它包含的所有Action均有权限
             * */
            string controllername = Request.RequestContext.RouteData.Values["controller"].ToString().ToLower();
            this._UserModules = GetUserModule();
            if (null != this._UserModules)
                this._CurrentModule = this._UserModules.FirstOrDefault(u => u.Url != null && u.Url.ToLower().Contains(controllername));
            var noauthorize = this.GetType().GetCustomAttribute(typeof(NoAuthorizeAttribute));
            if (null == noauthorize && null == this._CurrentModule) //未授权非法访问
            {
                WebHelper.WriteCookie("cubic_login_error", "noauthorize");
                filterContext.Result = new RedirectResult("/Login/Index");
                return;
            }
            
        }

        private List<CubicFWNet.Data.SystemManage.Model.Module> GetUserModule()
        {
            var authorizeurldata = new List<CubicFWNet.Data.SystemManage.Model.Module>();
            var cachedata = CacheFactory.Cache().GetCache<List<CubicFWNet.Data.SystemManage.Model.Module>>("authorizeurldata_" + this.CurrentUserId.ToString());
            if (cachedata == null || cachedata.Count == 0)
            {
                authorizeurldata = app.LoadForUser(this.CurrentUserId, _OperatorModel.IsSystem);

                /*
                 * 缓存时间定为10分钟，以免修改用户权限之后，生效时等候时间过长
                 * 加这个缓存挺有必要，要不每次在执行Navbar时，还会重复的执行GetUserModule操作，产生多次同样的数据库IO
                 * 
                 * */
                CacheFactory.Cache().WriteCache(authorizeurldata, "authorizeurldata_" + this.CurrentUserId, DateTime.Now.AddMinutes(10));
            }
            else
            {
                authorizeurldata = cachedata;
            }
            return authorizeurldata;
        }


        [ChildActionOnly]
        public PartialViewResult Navbar()
        {            
            if(null!=this._UserModules)
            {
                var bar = this.GetNavBar();
                ViewBag.NavBar = bar;
                if (_CurrentModule != null)
                    ViewBag.CurrentNav = this._CurrentModule.Id.ToString();
            }
            
            return PartialView("_Navigation");
        }

        private string GetNavBar()
        {            
            var modules = this._UserModules;
            IEnumerable<TreeItem<CubicFWNet.Data.SystemManage.Model.Module>> moduleItem = 
                modules.GenerateTree(c => c.Id, c => c.ParentId);
            var nav = BuilderNavBar(moduleItem);
            return nav;
        }

        private static string BuilderNavBar(IEnumerable<TreeItem<CubicFWNet.Data.SystemManage.Model.Module>> modules)
        {
            StringBuilder sb = new StringBuilder();
            foreach (var module in modules)
            {
                if (module.Children.Any())
                {
                    sb.Append("<li class=\"treeview\" id=\"" + module.Item.Id.ToString() + "\">\r\n");
                    sb.Append("<a href=\"#\">\r\n");
                    sb.Append("<i class=\"fa " + module.Item.IconName + "\" ></i>\r\n");
                    sb.Append("<span>\r\n");
                    sb.Append("" + module.Item.Name + "\r\n");
                    sb.Append("</span>\r\n");
                    sb.Append("\r\n");
                    sb.Append("<span class=\"pull-right-container\">\r\n");
                    sb.Append("<i class=\"fa fa-angle-left pull-right\"></i>\r\n");
                    sb.Append("</span>\r\n");
                    sb.Append("</a>\r\n");
                    sb.Append("\r\n");
                    sb.Append("<ul class=\"treeview-menu\">");
                    sb.Append(BuilderNavBar(module.Children));
                    sb.Append("</ul>");
                    sb.Append("</li>\r\n");
                }
                else
                {
                    sb.Append("<li class=\"treeview\"  id=\"" + module.Item.Id.ToString() + "\">\r\n");
                    sb.Append("<a href=\"" + module.Item.Url + "\" >\r\n");
                    sb.Append("<i class=\"fa " + module.Item.IconName + "\"></i>\r\n");
                    sb.Append("<span> " + module.Item.Name + " </span>\r\n");
                    sb.Append("</a>\r\n");
                    sb.Append("\r\n");
                    sb.Append("</li>\r\n");
                }
            }
            return sb.ToString();
        }
    }
}
